/*
 * Copyright 2010 Gal Dolber. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions and limitations under the
 * License.
 */
package com.unnison.framework.rebind.guitview;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import com.unnison.framework.client.StandaloneView;
import com.unnison.framework.client.View;
import com.unnison.framework.client.WidgetView;
import com.unnison.framework.rebind.common.AbstractGenerator;

import java.util.Set;

public class GuitViewGenerator extends AbstractGenerator {

    static enum GuitViewType {
        COMPOSITE, WIDGET, STANDALONE
    }

    private GuitViewType viewType;
    private Class<? extends com.google.gwt.dom.client.Element> widgetElementClass;

    public GuitViewGenerator() {
        implementationPostfix = "_GuitViewImpl";
    }

    @Override
    protected void generate(SourceWriter writer) throws UnableToCompleteException {
        Set<String> uiFields = GuitViewHelper.findUiFields(baseClass, logger, false);

        writer.println("@UiTemplate(\"" + baseClass.getSimpleSourceName() + ".ui.xml" + "\")");
        String bindedType = "Widget";
        if (viewType.equals(GuitViewType.WIDGET)) {
            bindedType = widgetElementClass.getCanonicalName();
        }
        writer.println("public interface Binder extends UiBinder<" + bindedType + ", " + implName + ">{}");
        writer.println("private Binder binder = GWT.create(Binder.class);");

        writer.println("public void bind() {");
        switch (viewType) {
            case COMPOSITE:
                writer.println("initWidget(binder.createAndBindUi(this));");
                break;
            case WIDGET:
                writer.println("setElement(binder.createAndBindUi(this));");
                break;
            case STANDALONE:
                writer.println("binder.createAndBindUi(this);");
                break;
        }
        writer.println("}");

        for (String f : uiFields) {
            writer.println(f);
        }
    }

    @Override
    protected void processComposer(ClassSourceFileComposerFactory composer) {
        composer.addImport(UiField.class.getCanonicalName());
        composer.addImport(UiTemplate.class.getCanonicalName());
        composer.addImport(UiBinder.class.getCanonicalName());
        composer.addImport(Widget.class.getCanonicalName());
        composer.addImport(GWT.class.getCanonicalName());

        composer.addImplementedInterface(View.class.getCanonicalName());

        // Support for old GuitView. TODO Remove
        if (baseClass.isInterface() != null) {
            composer.addImplementedInterface(typeName);
        }

        viewType = GuitViewType.COMPOSITE;
        if (baseClass.isAnnotationPresent(WidgetView.class)) {
            viewType = GuitViewType.WIDGET;
            widgetElementClass = baseClass.getAnnotation(WidgetView.class).value();
        } else if (baseClass.isAnnotationPresent(StandaloneView.class)) {
            viewType = GuitViewType.STANDALONE;
        }
        switch (viewType) {
            case COMPOSITE:
                composer.setSuperclass(Composite.class.getCanonicalName());
                break;
            case WIDGET:
                composer.setSuperclass(Widget.class.getCanonicalName());
                break;
        }
    }
}
